package pe.tnova.generic.structure.project.springmvc.soruce;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.eclipse.jdt.core.IAnnotation;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IMemberValuePair;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;

import pe.tnova.generic.structure.project.springmvc.UI.OptionAtributoBean;
import pe.tnova.generic.structure.project.springmvc.UI.OptionEntidadBean;
import pe.tnova.generic.structure.project.springmvc.util.ConstantesTNOVA;
import pe.tnova.generic.structure.project.springmvc.util.PluginUtil;

public class AnalisyEntityClass {

	private static final Logger LOG = Logger.getLogger(AnalisyEntityClass.class.getName());

	private OptionEntidadBean optionEntidadBean;
	private IMethod[] metodos;
	private IField[] campos;
	private IType clase;

	private Map<String, Object> lstConstructores;
	private Map<String, List<String>> lstNombreCamposConstructores;
	private Map<String, Object> lstCampos;
	private List<OptionAtributoBean> lstCampoAtributoBeans;
	private Map<String,String> lstImportsAdicionasPorAtributosEntidad;
	private Map<String,String> lstAdicionasPorAtributosEntidad;
	private String strPackageDominio;

	private AnalisyEntityClass(OptionEntidadBean optionEntidadBean, String strPackageDominio) throws JavaModelException {
		this.optionEntidadBean = optionEntidadBean;
		clase = optionEntidadBean.getCompilationUnit().getTypes()[0];
		metodos = clase.getMethods();
		campos = clase.getFields();
		lstConstructores = new LinkedHashMap<String, Object>();
		lstNombreCamposConstructores = new LinkedHashMap<String, List<String>>();
		lstCampos = new LinkedHashMap<String, Object>();
		lstCampoAtributoBeans = new ArrayList<OptionAtributoBean>();
		lstImportsAdicionasPorAtributosEntidad = new LinkedHashMap<String, String>();
		lstAdicionasPorAtributosEntidad = new LinkedHashMap<String, String>();
		this.strPackageDominio = strPackageDominio;
	}

	public static AnalisyEntityClass newInstace(OptionEntidadBean optionEntidadBean, String strPackageDominio) throws JavaModelException {
		LOG.log(Level.INFO, "new instance de Analisis de la clase para:" + optionEntidadBean.getNombreEntidad());
		return new AnalisyEntityClass(optionEntidadBean,strPackageDominio);
	}

	public void setEstablecerAtributosEntidad() throws JavaModelException {
		IAnnotation[] annotaciones;
		OptionAtributoBean optionAtributoBean = null;
		String key = null;
		String tipoParametro = null;
		String lazy = null;
		for (IField campo : campos) {
			for (int i = 0; i < ConstantesTNOVA.ANOTACIONES_PERMITIDAS.length; i++) {
				annotaciones = campo.getAnnotations();
				for (IAnnotation iAnnotation : annotaciones) {
					if (iAnnotation.getElementName().equals(ConstantesTNOVA.ANOTACIONES_PERMITIDAS[i])) {
						tipoParametro = PluginUtil.getTipoAtributoSingnature(campo.getTypeSignature());
						optionAtributoBean = new OptionAtributoBean();
						optionAtributoBean.setCampo(campo);
						optionAtributoBean.setDependencia(false);
						if (!PluginUtil.isNull(PluginUtil.getClassJava(tipoParametro))) {
							key = ConstantesTNOVA.CAMPO + ConstantesTNOVA.UNDERLINE + campo.getElementName().toUpperCase();
							optionAtributoBean.setKey(key);
							if(PluginUtil.isNull(lstCampos.get(key))){
								lstCampos.put(optionAtributoBean.getKey(), campo.getElementName());								
							}else{
								break;
							}
						} else {
							key = tipoParametro.toUpperCase() + ConstantesTNOVA.UNDERLINE
									+ ConstantesTNOVA.CAMPO + ConstantesTNOVA.UNDERLINE + campo.getElementName().toUpperCase();
							optionAtributoBean.setKey(key);
							lazy = iAnnotation.getSource();
							if ( (lazy.indexOf(ConstantesTNOVA.LAZY) > 0) || (lazy.indexOf(ConstantesTNOVA.EAGER) > 0)  ) {
								if (	   ConstantesTNOVA.ANOTACIONES_PERMITIDAS[i].equals(ConstantesTNOVA.ANOTACIONES_DEPENDENCIA_MANYTOONE)
										|| ConstantesTNOVA.ANOTACIONES_PERMITIDAS[i].equals(ConstantesTNOVA.ANOTACIONES_DEPENDENCIA_ONETOMANY)
										|| ConstantesTNOVA.ANOTACIONES_PERMITIDAS[i].equals(ConstantesTNOVA.ANOTACIONES_DEPENDENCIA_ONETOONE)) {
									optionAtributoBean.setInnerQuery(ConstantesTNOVA.LEFT_JOIN_FETCH);
									optionAtributoBean.setPrefijoQuery(ConstantesTNOVA.SQL_SEA+ConstantesTNOVA.SUMA+"\""+campo.getElementName().substring(0,2).toLowerCase()+"\"");
								}
								if(PluginUtil.isNull(lstImportsAdicionasPorAtributosEntidad.get(tipoParametro)) && !(tipoParametro.equals(optionEntidadBean.getNombreEntidad()))){
									lstImportsAdicionasPorAtributosEntidad.put(tipoParametro,"import "+ strPackageDominio+ConstantesTNOVA.DONT+tipoParametro+ConstantesTNOVA.DONT_COMA);								
									lstAdicionasPorAtributosEntidad.put(tipoParametro, tipoParametro);
								}
								optionAtributoBean.setDependencia(true);
							}
							if(PluginUtil.isNull(lstCampos.get(key))){
								lstCampos.put(optionAtributoBean.getKey(), campo.getElementName());								
							}else{
								break;
							}
						}
						optionAtributoBean.setTipoJava((tipoParametro.equals("I")?"int":tipoParametro));
						optionAtributoBean.setValue(campo.getElementName());
						optionAtributoBean.setLstAdicionasPorAtributosEntidad(lstImportsAdicionasPorAtributosEntidad);
						lstCampoAtributoBeans.add(optionAtributoBean);
						break;
					}
				}
			}
		}
		LOG.log(Level.INFO, "Analisis de los campos : ");
		LOG.log(Level.INFO, lstCampos.toString());
		LOG.log(Level.INFO, lstCampoAtributoBeans.toString());
		optionEntidadBean.setLstImportsAdicionasPorAtributosEntidad(new ArrayList<String>(lstImportsAdicionasPorAtributosEntidad.values()));
		optionEntidadBean.setLstCampos(lstCampos);
		optionEntidadBean.setLstCampoAtributoBeans(lstCampoAtributoBeans);
	}

	public void setConstructores() throws JavaModelException {
		String[] parameterNames = null;
		StringBuilder strNameQuery = null;
		for (IMethod iMethod : metodos) {
			strNameQuery = new StringBuilder(ConstantesTNOVA.SQL_QUERY);
			strNameQuery.append(ConstantesTNOVA.UNDERLINE);
			if (iMethod.isConstructor()) {
				parameterNames = iMethod.getParameterNames();
				if (!PluginUtil.isNull(parameterNames)) {
					for (int i = 0; i < parameterNames.length; i++) {
						if (i > 0) {
							strNameQuery.append(ConstantesTNOVA.UNDERLINE);
						}
						strNameQuery.append(parameterNames[i].toUpperCase());
					}
					lstNombreCamposConstructores.put(strNameQuery.toString(), Arrays.asList(parameterNames));
					lstConstructores.put(strNameQuery.toString(), getContructorStringQuery(parameterNames));
				}
			}
		}
		LOG.log(Level.INFO, "Analisis de los construnctores : ");
		LOG.log(Level.INFO, lstNombreCamposConstructores.toString());
		LOG.log(Level.INFO, lstConstructores.toString());
		optionEntidadBean.setLstConstructores(lstConstructores);
		optionEntidadBean.setLstNombreCamposConstructores(lstNombreCamposConstructores);
	}

	private String getContructorStringQuery(String[] parameterNames) {
		StringBuilder strQuery = new StringBuilder(ConstantesTNOVA.SQL_SELECT);
		strQuery.append(ConstantesTNOVA.SUMA);
		strQuery.append(ConstantesTNOVA.NEW);
		strQuery.append(ConstantesTNOVA.SUMA);
		strQuery.append(ConstantesTNOVA.STR_ENTIDAD);
		strQuery.append(ConstantesTNOVA.SUMA);
		strQuery.append(ConstantesTNOVA.PAREN_IZ);
		strQuery.append(ConstantesTNOVA.SUMA);
		for (int i = 0; i < parameterNames.length; i++) {
			if (i > 0) {
				strQuery.append(ConstantesTNOVA.SUMA);
				strQuery.append("\""+ConstantesTNOVA.COMA+"\"");
				strQuery.append(ConstantesTNOVA.SUMA);
			}
			strQuery.append(ConstantesTNOVA.SQL_SEA);
			strQuery.append(ConstantesTNOVA.SUMA);
			strQuery.append(ConstantesTNOVA.CAMPO + ConstantesTNOVA.UNDERLINE + parameterNames[i].toUpperCase());
		}
		strQuery.append(ConstantesTNOVA.SUMA);
		strQuery.append(ConstantesTNOVA.PAREN_DE);
		strQuery.append(ConstantesTNOVA.SUMA);
		strQuery.append(ConstantesTNOVA.SQL_FROM);
		strQuery.append(ConstantesTNOVA.SUMA);
		strQuery.append(ConstantesTNOVA.STR_ENTIDAD);
		strQuery.append(ConstantesTNOVA.SUMA);
		strQuery.append(ConstantesTNOVA.SQL_SE);
		return strQuery.toString();
	}

	public void setEstablecerValorCBO() throws Exception {
		boolean tieneAnnotacion = false;
		optionEntidadBean.setValueOrerBy("id");
		IAnnotation[] annotaciones = clase.getAnnotations();
		String order = null;
		for (IAnnotation iAnnotation : annotaciones) {
			if(iAnnotation.getElementName().equals(ConstantesTNOVA.ANOTACION_VALUE_CBO)){
				for (IMemberValuePair iMemberValuePair : iAnnotation.getMemberValuePairs()){
					if(iMemberValuePair.getMemberName().equals(ConstantesTNOVA.ANOTACION_VALUE_CBO_CAMPOCBO)){
						optionEntidadBean.setValueCBO(String.valueOf(iMemberValuePair.getValue()));
						tieneAnnotacion = true;
					}
					if(iMemberValuePair.getMemberName().equals(ConstantesTNOVA.ANOTACION_VALUE_CBO_DEFAULTORDERBY)){
						order = String.valueOf(iMemberValuePair.getValue());
						if(order.equals(ConstantesTNOVA.ANOTACION_VALUE_CBO_NA)){
						}else{
							optionEntidadBean.setValueOrerBy(order);							
						}
					}
				}				
			}
		}
		if(!tieneAnnotacion){
			throw new Exception("Todas las Entidades deben tener a anotacion @"+ConstantesTNOVA.ANOTACION_VALUE_CBO+" y tener un valor la anotacin @"+ConstantesTNOVA.ANOTACION_VALUE_CBO_CAMPOCBO);
		}
	}

}
